﻿using System;
using System.Runtime.Caching;
using JetBrains.Annotations;
using SF.Code.Extension.BusinessHelper;
using SG.Lang.Dry.Base;
using SG.Lang.Dry.Mirrors;

namespace SG.Lang.Dry.Persistance
{
    internal static class Repository<TElement, TSpecific>
        where TElement : Element
        where TSpecific : struct
    {
        internal delegate TElement ElementFactory(ref ElementRecord elementRecord, ref TSpecific specific);

        internal static TElement ResolveElement(ref Guid guid, [NotNull] ElementFactory factory)
        {
            if (guid.Equals(Guid.Empty))
                return null;

            var cache = MemoryCache.Default;
            var key = GuidEx.GuidToBase64(ref guid);
            var cached = cache.Get(key) as TElement;
            if (cached != null)
                return cached;

            ElementRecord elementRecord;
            TSpecific specific;

            if (!Repository<ElementRecord>.TryGet(ref guid, out elementRecord))
                return null;

            if (!Repository<TSpecific>.TryGet(ref guid, out specific))
                return null;

            var element = factory(ref elementRecord, ref specific);
            cache.Add(key, element, new CacheItemPolicy { SlidingExpiration = TimeSpan.FromMinutes(5) });
            return element;
        }
    }
}
